#include "mapxml.h"
#include "actorbase.h"
#include "actorproperty.h"
#include "map.h"
#include <QDir>
#include <QtXml/QDomNode>
#include <QtXml/QDomElement>
#include <QtXml/QDomDocument>
#include <QtXml/QDomNodeList>
#include <QtXml/QDomText>
#include <QtXml\QDomProcessingInstruction>
#include "datatypedefine.h"
#include "actorfactory.h"
#include <QVector>
#include <QtGui\QMessageBox>

namespace CoreBase
{
	MapXML::MapXML():_actorFactory(NULL)
	{}

	MapXML::~MapXML()
	{}

	bool MapXML::openXMLFile(const QString& path, Map* map)
	{
		QFile xmlFile(path);
		if(!xmlFile.open(QIODevice::ReadWrite))     
		{   
			//log can't read
			return false;
		}
		QDomDocument domtree; 
		if(!domtree.setContent(&xmlFile))   
		{   
			xmlFile.close(); 
			return false;   
		}
		QDomElement  root = domtree.documentElement();   
		QDomNodeList  nodelist=root.childNodes();  
		int count=nodelist.length();
		for(int i=0;i<nodelist.length();i++)   
		{
			QDomNode childnode = nodelist.item(i);
			if(childnode.nodeName() == XML_ELEMENT_HEADER)
			{
				for(int j=0;j< childnode.childNodes().length();j++)
				{
					if(childnode.childNodes().item(j).nodeName() == XML_ELEMENT_NAME)
					{
						QString name = childnode.childNodes().item(j).toElement().text();
						map->setName(name);
					}
					else if(childnode.childNodes().item(j).nodeName() == XML_ELEMENT_DESCRIPTION)
					{
						QString description = childnode.childNodes().item(j).toElement().text();
						map->setDescription(description);
					}
					else if(childnode.childNodes().item(j).nodeName() == XML_ELEMENT_AUTHOR)
					{
						QString author = childnode.childNodes().item(j).toElement().text();
						map->setAuthor(author);
					}
					else if(childnode.childNodes().item(j).nodeName() == XML_ELEMENT_REFERENCE_UNITCONVERSION)
					{
						QString ref_unit_conversion = childnode.childNodes().item(j).toElement().text();
						map->setReferenceUnitConversion(ref_unit_conversion);
					}
					else if(childnode.childNodes().item(j).nodeName() == XML_ELEMENT_RESOURCE)
					{
						QString copyright = childnode.childNodes().item(j).toElement().text();
						map->setResource(copyright);
					}
					else if(childnode.childNodes().item(j).nodeName() == XML_ELEMENT_CREATETIMES)
					{
						QString createtimes = childnode.childNodes().item(j).toElement().text();
						map->setCreateDateTime(createtimes);
					}
				}
			}
			else if(childnode.nodeName() == XML_ELEMENT_EVENTS)
			{}
			else if(childnode.nodeName() == XML_ELEMENT_ACTORS)
			{
				for(int j=0;j< childnode.childNodes().length();j++)
				{
					QDomNode actornode = childnode.childNodes().item(j);
					QString actortype = actornode.toElement().attribute(XML_ELEMENT_TYPE,"");
					if(actortype == "")
						continue;
					ActorBase* newactor = getActorFactory()->createActorByDataType(actortype);
					if(newactor==NULL)
						continue;
					for(int m=0;m< actornode.childNodes().length();m++)
					{
						QDomNode actornodechild = actornode.childNodes().item(m);
						if(actornodechild.nodeName() == XML_ELEMENT_ID)
						{
							newactor->setId(actornodechild.toElement().text());
						}
						else if(actornodechild.nodeName() == XML_ELEMENT_NAME)
						{
							newactor->setName(actornodechild.toElement().text());
						}
						else if(actornodechild.nodeName() == XML_ELEMENT_PROPERTY)
						{
							QString name = "";
							QString propertytype = "";
							QString value = "";
							for(int k=0;k< actornodechild.childNodes().length();k++)
							{
								QDomNode propertychildnode = actornodechild.childNodes().item(k);
								if(propertychildnode.nodeName() == XML_ELEMENT_NAME)
								{
									name = propertychildnode.toElement().text();
								}
								else
								{
									propertytype = propertychildnode.nodeName();
									value = propertychildnode.toElement().text();
								}
								if(name!="" && value!="")
								{
									CoreBase::ActorProperty* propertyobj = newactor->getProperty(name);
									if(propertyobj!=NULL)
										bool result = propertyobj->fromString(value);
								}
							}
						}
					}
					map->addActor(*newactor);
				}
			}
		}
		xmlFile.close();
		return true;
	}

	bool MapXML::saveXMLFile(const QString& path, Map* map)
	{
		QFile xmlFile(path);
		if(!xmlFile.open(QIODevice::WriteOnly|QIODevice::Text))     
		{   
			//log
			return false;
		} 
		QDomDocument domtree; 
		QDomText text;
		domtree.documentElement().clear();
		QDomProcessingInstruction instruction;
		instruction = domtree.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
		domtree.appendChild( instruction);
		//map
		QDomElement mapelement = domtree.createElement(XML_ELEMENT_MAP);
		domtree.appendChild(mapelement);
		//header
		QDomElement headerelement = domtree.createElement(XML_ELEMENT_HEADER);
		mapelement.appendChild(headerelement);

		QDomElement mapnameelement = domtree.createElement(XML_ELEMENT_NAME);
		headerelement.appendChild(mapnameelement);
		text = domtree.createTextNode(map->getName());
		mapnameelement.appendChild(text);

		QDomElement mapdescriptionelement = domtree.createElement(XML_ELEMENT_DESCRIPTION);
		headerelement.appendChild(mapdescriptionelement);
		text = domtree.createTextNode(map->getDescription());
		mapdescriptionelement.appendChild(text);

		QDomElement mapauthorelement = domtree.createElement(XML_ELEMENT_AUTHOR);
		headerelement.appendChild(mapauthorelement);
		text = domtree.createTextNode(map->getAuthor());
		mapauthorelement.appendChild(text);

		QDomElement maprucelement = domtree.createElement(XML_ELEMENT_REFERENCE_UNITCONVERSION);
		headerelement.appendChild(maprucelement);
		text = domtree.createTextNode(map->getReferenceUnitConversion());
		maprucelement.appendChild(text);

		QDomElement mapcopyrightelement = domtree.createElement(XML_ELEMENT_RESOURCE);
		headerelement.appendChild(mapcopyrightelement);
		text = domtree.createTextNode(map->getResource());
		mapcopyrightelement.appendChild(text);

		QDomElement mapcreatetimeselement = domtree.createElement(XML_ELEMENT_CREATETIMES);
		headerelement.appendChild(mapcreatetimeselement);
		text = domtree.createTextNode(map->getCreateDateTime());
		mapcreatetimeselement.appendChild(text);
		//events
		QDomElement eventselement = domtree.createElement(XML_ELEMENT_EVENTS);
		mapelement.appendChild(eventselement);
		//actors
		QDomElement actorselement = domtree.createElement(XML_ELEMENT_ACTORS);
		mapelement.appendChild(actorselement);
		QVector<osg::ref_ptr<ActorBase>> allactors;
		map->getAllActors(allactors);
		for(int i = 0;i < allactors.size();++i)
		{
			ActorBase* curActor = allactors.at(i);
			QDomElement actorelement = domtree.createElement(XML_ELEMENT_ACTOR);
			actorselement.appendChild(actorelement);
			actorelement.setAttribute(XML_ELEMENT_TYPE,curActor->getClassName());
			QDomElement actoridelement = domtree.createElement(XML_ELEMENT_ID);
			text = domtree.createTextNode(curActor->getId());
			actoridelement.appendChild(text);
			actorelement.appendChild(actoridelement);
			QDomElement actornameelement = domtree.createElement(XML_ELEMENT_NAME);
			text = domtree.createTextNode(curActor->getName());
			actornameelement.appendChild(text);
			actorelement.appendChild(actornameelement);
			//property
			QVector<ActorProperty*> propertylist;
			curActor->getPropertyList(propertylist);
			for(int j = 0;j<propertylist.size();++j)
			{
				ActorProperty* curproperty = propertylist.at(j);
				QDomElement actorpropertyelement = domtree.createElement(XML_ELEMENT_PROPERTY);
				actorelement.appendChild(actorpropertyelement);
				QDomElement propertynameelement = domtree.createElement(XML_ELEMENT_NAME);
				text = domtree.createTextNode(curproperty->getName());
				propertynameelement.appendChild(text);
				actorpropertyelement.appendChild(propertynameelement);
				QDomElement propertyvalueelement = domtree.createElement(curproperty->getDataType());
				text = domtree.createTextNode(curproperty->toQString());
				propertyvalueelement.appendChild(text);
				actorpropertyelement.appendChild(propertyvalueelement);				
			}
		}
		QTextStream out(&xmlFile);
		domtree.save(out,4,QDomNode::EncodingFromTextStream);
		xmlFile.close();
		return true;
	}

	ActorFactory* MapXML::getActorFactory()
	{
		return _actorFactory;
	}
}